/*
 * CommandHandler.cpp
 *
 *  Created on: 13.12.2012
 *      Author: Lapchinskiy
 */
#include "Global_types.h"
#include "ArrayList.h"
#include "Scheduler.h"
#include "StringManager.h"
#include "CommandHandler.h"
#include "ConditionBlock.h"
#include "Task.h"
#include "Scheduler.h"
#include "Logging.h"
#include "SerialInterface.h"
const char* EventToString[] =
  {
  "NONE", "SYS_TICK", "OBTURATOR_SLOPE", "COMMAND_RECEIVED"
  };
uint8_t CommandHandler::messageBufIndex = 0;
ArrayList *CommandHandler::globalTaskList = new ArrayList();
const uint8_t CommandHandler::messageEndChar = '\r';
const char *CommandHandler::commandNotFoundResponse = "\r\ncommand not found!";
const char *CommandHandler::permissionDeniedResponse = "->Permission denied!\r\n";
const char *CommandHandler::okResponse = "\r\nOK";
const char CommandHandler::commandsTable[MAX_COMMAND_NUMBER][MAX_CMD_STRING_LENTH] =
  {
    {
    "ls"
    },
    {
    "top"
    },
    {
    "peek"
    },
    {
    "set"
    },
    {
    "ex"
    },
    {
    "en"
    },
    {
    "dis"
    },
    {
    "logen"
    },
    {
    "logdis"
    },
    {
    "clear"
    }

  };
//typedef enum {
//	TASK_LIST,
//	TOP,
//	READ,
//	TASK_FUNC_EXECUTE,
//	TASK_ENABLE,
//	TASK_DISABLE,
//    FALSE_CMD,
//} CommandType
uint8_t* CommandHandler::messageBuf = 0;
CommandHandler::CommandHandler()
  {
    SerialPutString(">>> ");
    // TODO Auto-generated constructor stub

  }

ErrorCode CommandHandler::OnCommandReceived(void *args)
  {
    CommandType cmd = retrieveCommandFromString();
    uint8_t *paramPtr = messageBuf + StringManager::getLength((char*) commandsTable[cmd]) + 1;
    switch (cmd)
      {
      case TASK_LIST:
        //ArrayList<Task> *taskLists;
        //taskLists = Scheduler::getTaskLists();
        PutStringToTerminal("\r\n");
        PutStringToTerminal("ID:");
        for (uint16_t k = 0; k < 5; k++)
          {
            PutStringToTerminal(" ");
          }
        PutStringToTerminal("Name:");
//                	for (uint16_t k = 0; k < 8; k++) {
//			PutStringToTerminal(" ");
//		}
        MultiPutStringToTerminal(" ", StringManager::MAX_STRING_LENGTH - 5 - 15);
        PutStringToTerminal("Status:\r\n");
        MultiPutStringToTerminal("-", StringManager::MAX_STRING_LENGTH);
        PutStringToTerminal("\r\n");
//		for (uint8_t i = 0; i < MAX_EVENT_NUMBER; i++) {
        //	if (globalTaskList->getLength() != 0) {
        //	char *eventName=(char*) EventToString[i];
        //	MultiPutStringToTerminal("-",15-(StringManager::getLength(eventName) / 2));
        //PutStringToTerminal((char*) EventToString[i]);
        //	PutStringToTerminal(" event listeners:");
        //	MultiPutStringToTerminal("-",15-(StringManager::getLength(eventName) / 2));
        //PutStringToTerminal("\r\n");
        for (uint8_t j = 0; j < globalTaskList->getLength(); j++)
          {
            uint8_t taskId = ((Task*) (globalTaskList->get(j)))->getId();
            PutNumberToTerminal(taskId);
            uint8_t idDigits = 1;
            while ((taskId /= 10) > 0)
              {
                idDigits++;
              }
            MultiPutStringToTerminal(" ", 5 - idDigits + 3);
            PutStringToTerminal(((Task*) (globalTaskList->get(j)))->logrec.objectName);
            uint8_t temp = StringManager::getLength(((Task*) (globalTaskList->get(j)))->logrec.objectName);
            temp = StringManager::MAX_STRING_LENGTH
                - StringManager::getLength(((Task*) (globalTaskList->get(j)))->logrec.objectName) - 15;
            MultiPutStringToTerminal(" ", temp);
            PutStringToTerminal((char*) TaskStatusToString[((Task*) (globalTaskList->get(j)))->GetStatus()]);
            PutStringToTerminal("\r\n");
          }
        PutStringToTerminal("\b\b"); //two backspaces;
        break;
      case READ_BY_ADDR:
        {
          uint32_t addr;
          uint8_t str[10];
          StringManager::Str2Int((char*) (paramPtr), (int*) &addr); //get address to read
          StringManager::Int2Str(str, *(unsigned int*) addr); //read from address
          PutStringToTerminal("\r\n");
          PutStringToTerminal((char*) str);
          break;
        }
      case WRITE_TO_ADDR:
        {
          uint32_t addr;
          //uint8_t str[10];
          int16_t argPos;
          uint32_t value;
          StringManager::Str2Int((char*) (paramPtr), (int*) &addr); //get address to to write to
          argPos = StringManager::FindCharPosition((char*) paramPtr, ' ', 1) + 1; //get value position
          StringManager::Str2Int((char*) (paramPtr + argPos), (int*) &value); //get value to write
          *(unsigned int*) addr = value;
          PutStringToTerminal((char*) okResponse);
          break;
        }

      case TASK_FUNC_EXECUTE:
        {
          int32_t taskId;
          int32_t param;
          int16_t argPos;
          //     argPos =StringManager::FindCharPosition((char*)paramPtr,' ',1); //first param
          StringManager::Str2Int((char*) (paramPtr), &taskId); //get task Id
          argPos = StringManager::FindCharPosition((char*) paramPtr, ' ', 1) + 1; //first param
          Task* task;
          task = (Task*) globalTaskList->get(taskId);
          if (task->callbackFunc != &CommandHandler::OnCommandReceived)
            {
              if (argPos != 0)
                {
                  StringManager::Str2Int((char*) (paramPtr + argPos), &param);
                  task->CallbackRun((void*) &param);
                  //PutStringToTerminal((char*) okResponse);
                }
              else
                {
                  task->CallbackRun(task->getCallbackArgs());
                }
            }
          else
            {
              PutStringToTerminal((char*) permissionDeniedResponse);
            }

          break;
        }
      case TASK_ENABLE:
      case TASK_DISABLE:
        {
          int32_t taskId;
          StringManager::Str2Int((char*) (paramPtr), &taskId); //get task Id
          Task* task;
          task = (Task*) globalTaskList->get(taskId);
          if (task->callbackFunc != &CommandHandler::OnCommandReceived)
            {
              if (cmd == TASK_ENABLE)
                {
                  task->Enable();
                }
              else
                {
                  task->Disable();
                }
              PutStringToTerminal((char*) okResponse);
            }
          else
            {
              PutStringToTerminal((char*) permissionDeniedResponse);
            }
          break;
        }
      case LOGGING_ENABLE:
        LoggingEnable(true);
        PutStringToTerminal((char*) okResponse);
        break;
      case LOGGING_DISABLE:
        LoggingEnable(false);
        PutStringToTerminal((char*) okResponse);
        break;
      case CLEAR_SCREEN:
        SerialPutChar(0x0C); //clear screen
        break;
      case FALSE_CMD:
      default:
        PutStringToTerminal((char*) commandNotFoundResponse);
        break;

      }
    if (cmd != CLEAR_SCREEN)
      {
        SerialPutString("\r\n>>> ");
      }
    else
      {
        SerialPutString(">>> ");
      }
    return NO_ERR;
  }

Block* CommandHandler::Init(volatile uint32_t* eventMask)
  {
   messageBuf = new uint8_t[MAX_CMD_STRING_LENTH];
   Task *commandHandleTask = new Task((char*) "Command handler", &CommandHandler::OnCommandReceived, (void*) NULL,
        ENABLED);
#ifdef GLOBAL_LOGGING_ENABLE
    commandHandleTask->logrec.logEnable = false;
#endif // GLOBAL_LOGGING_ENABLE
   volatile unsigned int *null= new volatile unsigned int(0);
   volatile uint32_t *commandReceivedFlag = new volatile uint32_t(1 << COMMAND_RECEIVED);
    ConditionBlock<volatile uint32_t>* condCommHandleBlock = new ConditionBlock<volatile uint32_t>
      (new Condition<volatile uint32_t>(eventMask, AND, commandReceivedFlag, NOT_EQUAL, null));
    condCommHandleBlock->setNextYesBlock(commandHandleTask);
    commandHandleTask->setNexBlock(condCommHandleBlock);
    SerialPutString("\r\n>>> ");
    return condCommHandleBlock;
  }

CommandType CommandHandler::retrieveCommandFromString(void)
  {
    CommandType cmd = FALSE_CMD;

    for (uint8_t i = 0; i < MAX_COMMAND_NUMBER; i++)
      {
        if (StringManager::Compare((char*) commandsTable[i], (char*) messageBuf) == true)
          {
            cmd = (CommandType) i;
            break;
          }
      }
    messageBufIndex = 0;
    return cmd;
  }

//uint8_t CommandHandler::getMessageEndChar()  {
//	return CommandHandler::messageEndChar;
//}
ErrorCode CommandHandler::RegisterTask(Task *task)
  {
    return globalTaskList->add(task);
  }
CommandHandler::~CommandHandler()
  {
    // TODO Auto-generated destructor stub
  }

